import requests

from collections import namedtuple

Result = namedtuple('Result', 'code message data')
Result.__new__.__defaults__ = (False, '', None)

# 开发版
MINIPROGRAM_STATE_DEVELOPER = 'developer'
# 体验版
MINIPROGRAM_STATE_TRIAL = 'trial'
# 正式版
MINIPROGRAM_STATE_FORMAL = 'formal'

# 用户加入通知
MESSAGE_TYPE_ID_USER_JOIN_NOTIFY = 'dS2OfMrWGBLgEbcy2RISRZEMwA0I3pPKd6ddODU5Ghk'
MESSAGE_TYPE_PATH_USER_JOIN_NOTIFY = 'pages/subscribe/index'

# 告警通知
MESSAGE_TYPE_ID_ALERT = 'N5xvLGXPDaUpbMMQY4NWNINocDY8YXLRHKdCK1MGwqk'
MESSAGE_TYPE_PATH_ALERT = 'pages/my/index'


class WeiXinUser(object):

    def __init__(self, appid, secret):
        self.appid = appid
        self.secret = secret

    def get_open_id(self, code=''):
        url = f"https://api.weixin.qq.com/sns/jscode2session?appid={self.appid}&secret={self.secret}&j" \
              f"s_code={code}&grant_type=authorization_code"
        response = requests.get(url).json()
        if response.get('openid'):
            return Result(True, '', response['openid'])
        else:
            return Result(False, response.get('errmsg', ''))

    def get_unique_id(self, access_token, open_id):
        """
        subscribe: 用户是否订阅该公众号标识，值为0时，代表此用户没有关注该公众号
        openid: 用户的标识，对当前公众号唯一
        language: response['language'],
        subscribe_time: 用户关注时间，为时间戳。如果用户曾多次关注，则取最后关注时间
        unionid: 只有在用户将公众号绑定到微信开放平台账号后，才会出现该字段
        remark: 公众号运营者对粉丝的备注，公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
        groupid: 用户所在的分组ID（兼容旧的用户分组接口）
        tagid_list: 用户被打上的标签ID列表
        subscribe_scene: 返回用户关注的渠道来源
            ADD_SCENE_SEARCH 公众号搜索
            ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移
            ADD_SCENE_PROFILE_CARD 名片分享
            ADD_SCENE_QR_CODE 扫描二维码
            ADD_SCENE_PROFILE_LINK 图文页内名称点击
            ADD_SCENE_PROFILE_ITEM 图文页右上角菜单
            ADD_SCENE_PAID 支付后关注
            ADD_SCENE_WECHAT_ADVERTISEMENT 微信广告
            ADD_SCENE_REPRINT 他人转载
            ADD_SCENE_LIVESTREAM 视频号直播
            ADD_SCENE_CHANNELS 视频号
            ADD_SCENE_WXA 小程序关注
            ADD_SCENE_OTHERS 其他
        """
        url = f'https://api.weixin.qq.com/cgi-bin/user/info?access_token={access_token}&openid={open_id}&lang=zh_CN'
        response = requests.get(url).json()
        if response.get('openid'):
            return Result(True, response, '')
        else:
            return Result(False, message=str(response))

    def get_access_token(self):
        url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&" \
              f"appid={self.appid}&secret={self.secret}"
        response = requests.get(url).json()
        if response.get('access_token'):
            return Result(True, '', response['access_token'])
        else:
            return Result(False, '', None)

    @staticmethod
    def uniform_send_message(token, message_id, page_path, form_id, emphasis_keyword, params, to_user):
        """
        下发小程序和公众号统一的服务消息
        """
        url = f"https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token={token}"
        data = {}
        for key in params.keys():
            data[key] = {'value': params[key]}
        params = {
            'touser': to_user,
            'weapp_template_msg': {
                'template_id': message_id,
                'page': page_path,
                'form_id': form_id,  # 表单编号
                'emphasis_keyword': emphasis_keyword,  # 需要放大的关键字段名
                'data': data,
            }
        }
        response = requests.post(url, data=params).json()
        if response.get('errcode') == 0:
            return Result(True, '', None)
        else:
            return Result(False, response.get('errmsg'), None)

    @staticmethod
    def subscribe_send_message(token, message_id, page_path, params, to_user,
                               miniprogram_state=MINIPROGRAM_STATE_TRIAL):
        """
        发送用户订阅消息
        """
        url = f"https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={token}"
        data = {}
        for key in params.keys():
            data[key] = {'value': params[key]}
        params = {
            'template_id': message_id,
            'page': page_path,
            'touser': to_user,
            'data': data,
            'miniprogram_state': miniprogram_state,
            'lang': 'zh_CN',
        }
        response = requests.post(url, json=params).json()
        if response.get('errcode') == 0:
            return Result(True, '', None)
        else:
            return Result(False, response.get('errmsg'), None)
